package com.xcity.game.combat.listener.combat;

import java.text.MessageFormat;
import java.util.Arrays;

import com.xcity.db.entity.Player;
import com.xcity.game.arena.ArenaUtils;
import com.xcity.game.combat.Combat;
import com.xcity.game.combat.Combat.Type;
import com.xcity.game.combat.CombatBuilder;
import com.xcity.game.combat.CombatException;
import com.xcity.game.combat.CombatService;
import com.xcity.game.combat.Round;
import com.xcity.game.combat.builder.DefaultCombatBuilder;
import com.xcity.game.combat.listener.CombatListener;
import com.xcity.game.common.GameStaticConfig;
import com.xcity.game.common.MessageConst;
import com.xcity.game.event.GameEvents;
import com.xcity.game.formation.Formation;
import com.xcity.game.player.cache.PlayerCacheService;
import com.xcity.pomelo.push.msg.CombatEndPush;
import com.xcity.pomelo.request.CombatArenaOfflineRequest;
import com.xcity.pomelo.request.CombatInfoRequest;
import com.xcity.pomelo.response.CombatInfoResponse;
import com.xcity.pomelo.response.CombatInfoResponse.Team;
import com.xcity.pomelo.response.CombatInfoResponse.TeamBuilder;
import com.xcity.pomelo.response.CombatResponse;

import naga.x.App;
import naga.x.net.Packet;
import naga.x.net.Session;

public class ArenaOfflineCombatListener implements CombatListener {

	protected Player source, target;
	
	@Override
	public CombatResponse create(CombatService service, Type type, Session session, Packet packet) throws CombatException {
		CombatArenaOfflineRequest req = (CombatArenaOfflineRequest) packet;
		if (req.getId() == 0) {
			throw new CombatException(MessageConst.ILLEGAL_OPERATION);
		}
		source = session.getClient();
		if (source.getLevel() < GameStaticConfig.arenaOpenLvl) {
			throw new CombatException(MessageFormat.format(MessageConst.ARENA_LEVEL_LIMIT, GameStaticConfig.arenaOpenLvl));
		}
		target = App.getApp().getServiceManager().get(PlayerCacheService.class).find(req.getId());
		if (target == null) {
			throw new CombatException(MessageConst.PLAYER_NOT_EXIST);
		}
		ArenaUtils.tryJoin(source);
//		long[] targetEids = CombatUtils.getDefenseFormation(target);
//		long[] targetEids = target.getFormations().get(Formation.TYPE_ARENA_DEFENSE).getIds();
//		if (isFormationEmpty(targetEids)) {
//			targetEids = target.getFormations().get(Formation.TYPE_NORMAL).getIds();//CombatUtils.getCombatFormation(target, true);
//		}
//		long[] sourceEids = source.getFormations().get(Formation.TYPE_NORMAL).getIds();
//		Combat combat = new PVPCombatBuilder()
//				.setType(type)
////				.setSource(source).setSourceEmployeeIds(sourceEids)
//				.setTarget(target).setTargetEmployeeIds(targetEids)
//				.setListener(this)
//				.build();
		
		CombatBuilder builder = new DefaultCombatBuilder()
				.setType(type)
				.setListener(this)
				.setSourceLeader(source)
				.addSourceMembers(Arrays.asList(source.getFormations().get(Formation.TYPE_NORMAL).getUnits()))
				.setDestLeader(target)
				.addDestMembers(Arrays.asList(target.getFormations().get(Formation.TYPE_ARENA_DEFENSE).getUnits()));
		return new CombatResponse(req.getSerial(), builder.build());
	}
	
	static boolean isFormationEmpty(long[] eids) {
		for (int i = eids != null ? eids.length - 1 : -1; i >= 0; i--) {
			if (eids[i] != 0L) {
				return false;
			}
		}
		return true;
	}

	@Override
	public void end(Combat combat, boolean notify) {
		boolean succ = combat.isWinner(source.getId());
		int honor = source.getHonor();
		App.getApp().getEventManager().fireEvent(GameEvents.EVENT_ARENA_END, source, target.getId(), succ);
		if (notify) {
			source.send(new CombatEndPush(succ ? Combat.SUCC : Combat.FAIL, Combat.Type.ARENA_OFFLINE, combat.getId(), succ ? new Result(source.getHonor() - honor) : null));
		}
	}

	@Override
	public void prepareCombat(Session session, CombatInfoRequest packet) throws CombatException {
		long targetId = packet.getArenaTargetId();
		if (targetId == 0) {
			throw new CombatException(MessageConst.ILLEGAL_OPERATION);
		}
		source = session.getClient();
		if (source.getLevel() < GameStaticConfig.arenaOpenLvl) {
			throw new CombatException(MessageFormat.format(MessageConst.ARENA_LEVEL_LIMIT, GameStaticConfig.arenaOpenLvl));
		}
		target = App.getApp().getServiceManager().get(PlayerCacheService.class).find(targetId);
		if (target == null) {
			throw new CombatException(MessageConst.PLAYER_NOT_EXIST);
		}
		
		TeamBuilder sourceTeamBuilder = new TeamBuilder().setLeader(source);//.setCombatPower(CombatUtils.calcCombatPowerWithEmployees(source));
		long[] srcEmployeeIds = source.getFormations().get(Formation.TYPE_NORMAL).getIds();//CombatUtils.getCombatFormation(source, true);
		for (long eid : srcEmployeeIds) {
			sourceTeamBuilder.addEmployeeMember(eid);
		}
		
		Team sourceTeam = sourceTeamBuilder.build();
		
		TeamBuilder targetTeamBuilder = new TeamBuilder().setLeader(target);//.setCombatPower(CombatUtils.calcCombatPowerWithEmployees(target));
		long[] tgtEmployeeIds = target.getFormations().get(Formation.TYPE_ARENA_DEFENSE).getIds();//CombatUtils.getCombatFormation(target, true);
		for (long eid : tgtEmployeeIds) {
			targetTeamBuilder.addEmployeeMember(eid);
		}
		Team targetTeam = targetTeamBuilder.build();
		
		session.send(new CombatInfoResponse(packet.getSerial(), sourceTeam, targetTeam, Formation.TYPE_NORMAL));
	}
	
	static class Result {
		int honor;
		int gold;
		public Result(int honor) {
			this.honor = honor;
		}
		public int getHonor() {
			return honor;
		}
		public int getGold() {
			return gold;
		}
	}

	@Override
	public void roundStart(Round round) {
	}

	@Override
	public void roundEnd(Round round) {
	}

}
